home *** CD-ROM | disk | FTP | other *** search
/ Freaks Macintosh Archive / Freaks Macintosh Archive.bin / Freaks Macintosh Archives / PC / MOBITEX.ZIP / MOBITEX.TXT < prev   
Internet Message Format  |  1997-03-14  |  63KB

  1. From arron5@geocities.com Fri Mar 14 18:12:20 1997
  2. Path: ix.netcom.com!ix.netcom.com!netnews.com!howland.erols.net!news.sgi.com!news.msfc.nasa.gov!info.uah.edu!jim    
  3. From: arron <arron5@geocities.com>
  4. Newsgroups: rec.radio.scanner
  5. Subject: Fun mobitex stuff
  6. Date: Fri, 14 Mar 1997 18:12:20 -0800
  7. Organization: The University of Alabama in Huntsville
  8. Lines: 1365
  9. Message-ID: <332A0580.FB0@geocities.com>
  10. Reply-To: arron5@geocities.com
  11. NNTP-Posting-Host: 146.229.22.52
  12. Mime-Version: 1.0
  13. Content-Type: text/plain; charset=iso-8859-1; name="MOBITEX.TXT"
  14. Content-Transfer-Encoding: 8bit
  15. X-Mailer: Mozilla 3.01 (Win16; I)
  16. Content-Disposition: inline; filename="MOBITEX.TXT"
  17.  
  18.  
  19.                 THE INHERENT INSECURITY OF DATA OVER
  20.                 MOBITEX WIRELESS PACKET DATA NETWORKS
  21.  
  22.  
  23.  
  24. TABLE OF CONTENTS
  25.  
  26. 1. Introduction
  27. 2. The Mobitex Protocol
  28. 3. RAM Mobile Data's U.S. Mobitex network
  29. 4. stupid stuff
  30. 5. Humor Section - What some major companies say about Mobitex security
  31. 6. The scanner to computer interface
  32. 7. How to compile and use the attached program
  33. 8. Program listing
  34.  
  35. ***********************************************************************
  36. 1.                          Introduction
  37. ***********************************************************************
  38.  
  39.      The Mobitex wireless data network standard was originally developed
  40. in Sweden in the 1980's and successfully marketed by Ericsson. Over the
  41. years Mobitex networks have sprouted up in numerous countries around the
  42. globe as Ericsson's world wide web page (http://www.ericcson.com) points
  43. out. So no matter where you are reading this there might be Mobitex
  44. network in operation near you. If so, this posting and attached program
  45. gives you all the information you need to intercept and decode whatever
  46. information is flowing over your local system. The required equipment is
  47. easily availble - you will need a scanner radio with discriminator
  48. output, a PC compatible computer, and a simple Op-amp based audio
  49. clipping circuit of the Hamcomm or PD203 Pocsag decoder type.
  50.  
  51.      The reader will find that a lot of information in this posting is
  52. geared towards one specific Mobitex network operated by RAM Mobile Data
  53. in the United States. Nonetheless, the included program has been written
  54. with flexibility in mind - with the proper configuration options set it
  55. should work with most any Mobitex system.
  56.  
  57.      Finally, one may ask whether this project is really worth the
  58. effort. The answer to that question probably depends on what sort of
  59. Mobitex systems are active in reader's vicinity. And one sure way of
  60. finding that out is by getting the described decoding system up and
  61. running. At that point the authors suppose it becomes a matter of
  62. personal taste - some people might find it a most satisfyingly orgasmic
  63. experience to watch appliance repair personnel being dispatched around
  64. their town while others move on to better things. For those
  65. contemplating monitoring the RAM network: it should be mentioned that
  66. this network uses a cellular architecture which means that traffic in
  67. your city will probably be divided over a number of channels reducing
  68. the number of messages you can intercept. The authors will say though
  69. that RAM's network does have plain ASCII messages whizzing around, one
  70. might just have to be a little patient.
  71.  
  72. ***********************************************************************
  73. 2.                       The Mobitex Protocol
  74. ***********************************************************************
  75.  
  76.  
  77. Basically we'll let an excerpt from RAM's whitepaper available on the
  78. world wide web do all the work.
  79.  
  80. from http://www.micron.net/~rmd/press/white_paper/security.html
  81.  
  82. > RADIO SIGNALING PROTOCOL (ROSI)
  83. >   ________________________________________________________________________
  84. >
  85. >  The MOBITEX network uses a Time Division Multiple Access (TDMA) method
  86. >  with a modified Slotted Aloha channel access algorithm. This unique
  87. >  channel access algorithm provides an efficient channel utilization.
  88. >  Data is sent over the airlink in short bursts at 8000 bps using
  89. >  Gaussian Minimum Shift Keying (GMSK) modulation, encoded and
  90. >  interleaved for error correction, and then scrambled.
  91. >
  92. >  Messages in the MOBITEX system are made up of packets (called MPAKs)
  93. >  at the network layer (OSI layer 3). In the radio modem, these are
  94. >  encapsulated for transmission over the radio link by protocols at the
  95. >  data link (OSI 2) and physical (OSI 1) layers. The data link layer of
  96. >  the radio modem performs all the required base band signal processing
  97. >  operations. The PMAKs are broken up into radio frames by the radio
  98. >  modem. A frame header of 56 bits is generated and placed in front of
  99. >  each radio frame. Data blocks consist of 20 bytes, each containing 8
  100. >  bits of data followed by four bits generated with a (12,8) Hamming
  101. >  code. A radio frame has up to 20 data blocks. In order to protect
  102. >  against burst error, interleaving in performed. The interleaving
  103. >  process can be viewed by imagining the data arranged as rows in a 12
  104. >  bits wide by 20 bits long matrix. The data is then sent column wise.
  105. >  Up to this point, the Hamming code corrects single bit errors per
  106. >  byte, and the interleaved code allows a burst of 20 errors to be
  107. >  corrected. The data following the frame head is then scrambled.
  108. >  Scrambling provides a mechanism to achieve DC voltage balance by
  109. >  eliminating long sequences of ones and zeros in the data stream. At
  110. >  this point, we have completed the necessary digital operations and are
  111. >  ready for RF processing. The modem then performs the GMSK modulation
  112. >  before applying the signal to the radio transceiver and onto the
  113. >  appropriate radio channel. The receive operation is the exact reverse
  114. >  of the transmit operation. A block diagram of the base band processing
  115. >  operations is shown in Figure 4
  116. >
  117. >  Receiving and transmitting data over the airlink in the MOBITEX
  118. >  network is a very complicated process. It is a difficult task for
  119. >  radio modem manufacturers, not to mention much less sophisticated
  120. >  hackers trying to break into the network. It may be more cost
  121. >  effective to break into the user's computer system, rather than the
  122. >  MOBITEX network since the technical expertise needed to break into the
  123. >  air interface is so extensive.
  124. >
  125.  
  126. Now just a brief explanation / amplification of some of the terms:
  127.  
  128. Aloha channel access - when the mobile transmits a message it expects an
  129.    acknowledgement from the base station. If it doesn't get it the
  130.    mobile assumes it transmitted at the same time as another mobile so
  131.    it waits a short, random period and tries again.
  132.  
  133. GMSK - This is basically the same thing as direct frequency shift keying
  134.    except the waveform is filtered to take all the sharp edges off so it
  135.    can fit in a narrower channel. This makes it more susceptible to
  136.    noise, but hey - you can't have everything.
  137.  
  138. BIT SCRAMBLING - like RAM says, it is done purely for technical reasons,
  139.    not to hide the contents of the data (but try explaining that to a
  140.    U.S. court after you get arrested for violating ECPA laws). The
  141.    scrambler is just a regular 9 stage shift register pseudo-random
  142.    white noise generator with feedback taps on the fifth and ninth
  143.    stages initialized at the start of the first data block. What if you
  144.    didn't know this? The interested reader will verify that if a
  145.    correlation were performed on data stream with two shifted versions
  146.    of itself (just perform a normal correlation twice in a row) you can
  147.    easily see that when one stream is shifted by 5 and the other by 9
  148.    bits that something special is happening. The tranmsitted data is
  149.    actually correlated enough for you to directly pick out the correct
  150.    shift register taps! The interested reader might also want to verify
  151.    that a regular correlation using only the bit stream and a single
  152.    shifted version of itself is absolutely useless. Those working on the
  153.    key recovery problem for certain versions of Motorola's digital voice
  154.    privacy (DVP) encryption using similar shift register techniques
  155.    might want to proceed along those lines (of course there are a hell
  156.    of a lot more taps to worry about).
  157.  
  158. FRAME HEADER -
  159.    For all Mobitex systems the first two bytes are bit sync:
  160.            CCCC for the base and 3333 for the mobiles.
  161.    The next two bytes are a system specific frame sync.
  162.            For RAM this will be B433.
  163.    The next two bytes are control bytes (again system specific):
  164.            FOR ram the first part gives system ID, the latter part is a
  165.            status. When Bits 1 and 2 of the second control byte are zero
  166.            then data blocks will follow the frame header.
  167.    The last byte provides FEC for the two control bytes.
  168.  
  169.    The program detects the Frame header by matching up the bit sync, the
  170.    frame sync (optional), and checking the FEC coding on the two control
  171.    bytes. When the frame header is detected it will either assume that a
  172.    data block is following the frame header (non RAM mode) or it checks
  173.    the control byte to see if a data block follows the frame header (RAM
  174.    mode). The frame sync is not necessarily followed by any data.
  175.  
  176. DATA BLOCK - the program processes the data block as follows:
  177.    undo the bit scrambling (if that option is set)
  178.    uninterleave the data
  179.    Run through the forward error correction (FEC) routine while keeping
  180.        track of the number of errors.
  181.    Calculate the CRC on this data block and compare with the received
  182.        CRC.
  183.    If the calculated CRC does not match the transmitted CRC and there
  184.        were a large number of FEC errors the programs decides that a
  185.        data block was actually not transmitted and goes back to hunting
  186.        for the frame header.
  187.    If a good data block was received it will go on and try to receive
  188.       another data block.
  189.  
  190. Basically then, the program cycles back and forth between hunting for
  191. the frame sync and printing out DATA blocks. The output format of the
  192. data blocks will look something like:
  193.  
  194. 6F6C6F6775653A2049424D204D6F62696C65A73B         ologue: IBM Mobileß;
  195.  
  196. or if the calculated CRC was bad it would have looked like:
  197.  
  198. 6E6C6F6775653A2049424D204D6F62696C65A73B BAD CRC nlogue: IBM Mobileß;
  199.  
  200. The last two bytes are the CRC; the first 18 bytes are the data.
  201. Whenever you see these types of blocks appearing on the screen then you
  202. can rest assured that you do indeed have the program configured
  203. properly. Keep in mind that your system might have very little actual
  204. traffic. Also, status message will appear as single data blocks (at
  205. least for the RAM network).
  206.  
  207.      If you the reader must know more then take a look a various
  208. semiconductor data sheets (example : look at the MXCOM's 909 Mobitex
  209. interface chip for a data sheet giving a lot of information on the
  210. mobitex protocol - http://www.mxcom.com/mx909Api.htm ). Also, more
  211. details on the RAM system can be found in the following article:
  212.  
  213.      M. Mobeen Khan, "Wireless dta over RAM's Mobitex network,"
  214.      Proceedings of the SPIE, Vol. 2601, pp. 48 - 53, 1995.
  215.  
  216. Of most interest is section 3 giving information on the network
  217. protocols. This would help one figure out the raw data blocks displayed
  218. by this program. The basic upshot - the first data block of a packet has
  219. the following format:
  220.  
  221.      BYTES 1-3  : Destination Mobitex Acess Number (MAN) - tells which
  222.                   mobile is to receive this packet
  223.      BYTES 4    : Frame ID
  224.      BYTE  5    : Sequence number
  225.      BYTE  6    : Number of data blocks in the packet
  226.  
  227.      The above 6 bytes are part of the Mobitex standard (data link
  228.      layer). The next are specific to the RAM network layer
  229.      implementation.
  230.  
  231.      BYTES 7-9   : Sender's MAN
  232.      BYTES 10-12 : Addressee MAN
  233.      BYTE  13    : State Flag
  234.      BYTE  14-18 : Packet ID
  235.  
  236.      BYTE  19-20 : CRC bytes - we're back to the Mobitex standard
  237.  
  238. The state flag can be used to send any one of 256 status messages to a
  239. specific terminal (this is application dependent). So don't be suprised
  240. to see a lot of single data blocks coming in over the air. The next data
  241. blocks (if any) are user data which can be virutally any kind of
  242. protocol. The included program does not take advantage of any of this
  243. fancy stuff - it simply displays the data blocks sent over the physical
  244. layer.
  245.  
  246.      For additional "security" each device that works on the RAM network
  247. has its own serial number in addition its mobitex access number. This
  248. serial number is verified every time the mobile logs on to RAM. No doubt
  249. readers will recognize that this is exactly the same process used to
  250. provide security for cellular phones in north America. One can only
  251. conclude that the RAM Mobile Data network is similarly waiting to be
  252. abused. The attached program could potentially be used to gobble up lots
  253. of MANs and their corresponding serial numbers as part of a cloning
  254. operation. The only reason that hasn't happened yet is that cloning
  255. cellular phones is a far more lucrative proposition. However, please
  256. don't misunderstand us - we're not trying to advocate or promote any
  257. sort of illegal activities.
  258.  
  259.  
  260.      Conclusions: Mobitex is truly the greatest contribution to the
  261. telecommunications industry from the Nordic countries. At this point the
  262. authors would be remiss if they failed to mention the greatest
  263. contribution to humanity from this part of the globe - mass quantities
  264. of cheap and legal pornography! What telecom nerd could ask for anything
  265. more?
  266.  
  267. ***********************************************************************
  268. 3.             How to identify RAM / Mobitex frequencies
  269. ***********************************************************************
  270.  
  271.      In the United States, RAM mobile data has built an extensive
  272. Mobitex network covering most of the larger cities. To verify RAM's
  273. coverage in your area take a look at the following link:
  274.  
  275.      http://www.ram-wireless.com/coverage/coverage_main.html
  276.  
  277. Once you have verified that you are indeed in the RAM coverage area you
  278. will want to find the right frequencies. In each of these areas RAM will
  279. have obtained at least one block of 10 individual frequencies somewhere
  280. in the 935-940MHz (Base) / 896-901MHz (Portable) band (with 12.5KHz
  281. channel spacing). The specific frequencies allocated vary from area to
  282. area. If you don't have access to a frequency database one can find the
  283. RAM's frequencies by scanning for channels with the following
  284. characteristics. The transmitter is always on. When the channel is idle
  285. there will be a background information burst transmitted roughly every
  286. half second or second. The best description for how a packet sounds
  287. would be a brief burst of white noise. Between packets the carrier will
  288. be unmodulated and you won't hear a thing. This means you want to find
  289. those channels that sound like "Chuff... Chuff... Chuff..." I don't know
  290. whether other Mobitex networks sound similar - after all, one needn't
  291. necessarily keep the transmitter on all the time, one might be running
  292. at a different baud rate, and if bit scrambling is not used the system
  293. might sound less like noise.
  294.  
  295.      The program options section gives a suggested procedure to follow
  296. for trying to receive unknown Mobitex systems.
  297.  
  298.      As an aside, anyone who has the ability to monitor Motorola mobile
  299. data terminals using the MDC4800 protocol (using a different program
  300. available on the internet) can monitor RAM's main competitor ARDIS.
  301. Their coverage maps and more information can be found at:
  302.  
  303.      http://www.ardis.com/ardis_hp/mapintro.htm
  304.  
  305. ***********************************************************************
  306. 4.                          Stupid stuff
  307. ***********************************************************************
  308.  
  309.      The program itself is absolutely free, not shareware. As such, the
  310. authors do not feel obligated to provide any support or updates beyond
  311. the information included in this text. Any attempts to personally
  312. contact the authors are doomed to failure since they have taken steps to
  313. remain anonymous.
  314.  
  315.      There are no restrictions on redistribution of this text file or
  316. the program. Mangle it, rewrite it, sell it (like you're going to get
  317. any money for this in the first place), whatever... see if the authors
  318. care - that's why there giving this away for free.
  319.  
  320.      If anyone has more information to add please post! Let us know of
  321. any major problems you run into. Please post to the rec.radio.scanner
  322. newsgroup - the authors are so cowardly that they do not want to admit
  323. to having regular internet access (which explains in part why this is
  324. being posted from a public terminal). Also, let everyone know if you
  325. find any active Mobitex systems other than RAM Mobile Data's and what
  326. they are used for.
  327.  
  328.      Anyone archiving this information or putting it on some world wide
  329. web page will probably want to delete the following paragraph. One of
  330. the authors absolutely insisted this paragraph be included although the
  331. others would have preferred not to.
  332.  
  333.      The authors exhort anyone reading this not be a parasitic
  334. internet douche sponge requesting and soaking up information for
  335. financial and egotistical reasons while giving nothing of value in
  336. return. As an illustration, an author profile of jvpoll@dallas.net taken
  337. from www.dejanews.com uncovers his step by step progress in the past
  338. year in attempting to build a device to track and follow trunked radio
  339. systems - pleadings on the sci.crypt newsgroup for help on decoding
  340. trunked radio control channel protocols, discussions on the
  341. sci.electronics.design newsgroup on how to protect his "proprietary"
  342. code and help on hooking up a LCD display, the incessant stream of
  343. advertising and ego building on the alt and rec.radio.scanner
  344. newsgroups, in addition to postings to various alt.recovery.* and
  345. alt.romance newsgroups. An author profile from www.dejanews.com only
  346. scratches the surface - it won't reveal things like membership in the
  347. North American Man Boy Love Association (apparently child molestors try
  348. to avoid public exposure) or how thick the layers of dried up semen
  349. crusts are on Jim's trousers and commercial products (potential
  350. customers are advised to delay ordering from Jim until male impotence
  351. finishes taking its terrible toll).
  352.  
  353. ***********************************************************************
  354. 5.                        Humor Section
  355. ***********************************************************************
  356.  
  357. For your entertainment this section gives excerpts from what two leading
  358. communication companies (RAM Mobile Data and Bellsouth) have to say
  359. about Mobitex data security on their web pages. If you don't believe
  360. these are real check out the http links for yourself.
  361.  
  362.  
  363. RAM Mobile Data -
  364.  
  365.    from http://www.micron.net/~rmd/press/white_paper/security.html
  366.  
  367. >  The combination of digital technology and packet data switching has
  368. >  produced a high degree of inherent security to safeguard the privacy
  369. >  of users' data. The additional use of sophisticated protocols and
  370. >  unique radio modem designs make it extremely difficult to tap into
  371. >  the MOBITEX networks.
  372.  
  373.  
  374. >  Receiving and transmitting data over the airlink in the MOBITEX
  375. >  network is a very complicated process. It is a difficult task for
  376. >  radio modem manufacturers, not to mention much less sophisticated
  377. >  hackers trying to break into the network. It may be more cost
  378. >  effective to break into the user's computer system, rather than the
  379. >  MOBITEX network since the technical expertise needed to break into
  380. >  the air interface is so extensive.
  381.  
  382.  
  383. >  There are many inherent security measures built into MOBITEX and a
  384. >  wide selection of network features capable of enhancing data
  385. >  security. Unless one is transmitting very sensitive data, one need
  386. >  not be apprehensive about data security on the MOBITEX networks.
  387.  
  388.  
  389. Bellsouth - from http://www.data-mobile.com/unshocked/security.html
  390.  
  391. >  Mobitex protocol provides a high level of security. Data
  392. >  transmissions over a wireless packet switched network are much more
  393. >  difficult to capture than voice transmissions over a cellular voice
  394. >  network. Unlike conversations in the cellular environment, which are
  395. >  continuous and easily monitored by unsophisticated eavesdroppers,
  396. >  messages in a packet switched environment are sent in bursts.
  397. >  "Reading" such messages is only possible if the RF interface can be
  398. >  descrambled, a process requiring a level of personnel skill and
  399. >  software sophistication that is prohibitive. In addition, Mobitex is
  400. >  compatible with customer selected security packages, thus enabling
  401. >  the user to choose additional security for select messages.
  402.  
  403.  
  404.      Conclusions: BULLSHIT. Especially when Mobitex is a public, freely
  405. available standard. The most challenging part of this project was
  406. actually getting the Mobitex documentaion, everything else was a
  407. programming excercise. Not that proprietary protocols would have been
  408. more difficult to figure out - just ask Motorola!
  409.  
  410.      Obviously the users of Mobitex networks have been lied to and raped
  411. by large corporate entities. The only real way to achieve data security
  412. over a Mobitex network is using real honest-to-god encryption. This
  413. decision is left up to each customer. The reader is invited to make an
  414. inspired guess as to how many customers actually choose to use real
  415. encryption after being told that it is virtually impossible for anyone
  416. to receive data transmitted over the radio link. The authors of this
  417. posting sincerely hopes that all those developers of portable terminals
  418. using RAM's network for credit card verification didn't listen too
  419. closely to what RAM was telling them.
  420.  
  421.      The authors urge everyone to contact these companies and point out
  422. to them the error of their ways. When doing so be sure to emphasize
  423. you're reading data off a RAM's network with an el-cheapo scanner, a few
  424. dollars worth of parts from Radio Shack, and some really shitty code
  425. floating around the internet. It can't hurt to lie and tell them you're
  426. a HACKER (god forbid!) going by a handle such as 'Brunhilde' and that
  427. you're using your skills to collect dozens of credit card numbers off of
  428. RAM's network each day. Maybe then they'll decide (along with Morotola)
  429. to do something to secure their mobile data terminal systems such as
  430. bribing enough Congress-creatures to pass a law mandating 20 year prison
  431. sentences for anyone who has ever bought an op-amp from Radio-Shack (and
  432. now you know why Radio-Shack maintains a computer database of all of its
  433. customers).
  434.  
  435.  
  436. ***********************************************************************
  437. 6.                The computer to scanner interface
  438. ***********************************************************************
  439.  
  440.      The interface described here will allow you to monitor not only
  441. Mobitex systems, but with different freely available software packages
  442. you can also monitor POCSAG paging signals (PD203 package), Motorola
  443. MDC4800 mobile data terminal transmissions (just ask on this newsgroup)
  444. decode Motorola trunked radio control channel information (see next
  445. blurb about a program called trunker.exe), and also shortwave RTTY and
  446. fax transmissions (HAMCOM and JVFAX software packages). Not too bad for
  447. a few dollars worth of parts!
  448.  
  449. ------ IRRELEVANT NON-MOBITEX INFORMATION WARNING!!! ------
  450.  
  451.      Some semi-new Motorola trunked radio control channel information
  452. for those poor souls palying around with trunker.exe: Those who might
  453. want to monitor 800MHz systems operating with some channels offset every
  454. 12.5KHz might want to look at my current best guess at the algorithm for
  455. converting a frequency assignment code into an actual frequency:
  456.  
  457. 1. If the code is < 0x2D0 then
  458.    Frequency = 851.0125 + (0.25 * code)
  459.  
  460. 2. For the remaining codes: if the code < 0x2f8 then
  461.    Frequency = 848.0000 + (0.25 * code)
  462.  
  463. 3. If  0x32f < code < 0x340:
  464.    Frequency = 846.6250 + (0.025 * code)
  465.  
  466. 4. If the code is > 0x3C0:
  467.    Frequency = 843.4000 + (0.025 * code)
  468.  
  469. I'm pretty sure 0x2f8, 0x340, and 0x3C0 are not frequency assigments -
  470. they define (within a spot or two) boundaries between blocks of
  471. information and frequency assignments. I've only been able to test this
  472. algorithm out on one system that used frequencies falling under cases
  473. 2,3, and 4 (anyone from the rural North Alabama or middle Tennessee
  474. areas will sympthasize with my plight) so there are no guarrantees that
  475. it works properly for every single frequency in your area. Any
  476. corrections to this information are welcome and thanks to whoever posted
  477. the right formula for 900MHz systems. And if you do post a message
  478. saying it's all screwed up include exactly which frequencies in your
  479. area aren't getting decoded correctly and maybe what this algorithm
  480. thought they were.
  481.  
  482.      For those who want to send information to your scanner and have
  483. trouble configuring the serial port you will definitely want to remove
  484. the following line from the set8250 routine:
  485.  
  486.   outportb (0x03fb, 0x00);     /*  set IER on 0x03f9 */
  487.  
  488. What this line did was to effectively undo the serial port parameter
  489. setup from just a few lines earlier.
  490.  
  491.      Finally, those of you messing around with ways to tell your
  492. computer when to switch back to the control channel might want to just
  493. detect the disconnect sequence (11001010 sent at 300 baud). This works
  494. even using just your present interface (no audio is being transmitted at
  495. that time) without an additional low-pass filter section feeding into
  496. your computer just for sub-audible information. It's incredibly cheesy
  497. but you'll find it actually works.
  498.  
  499. ---------------- Back to Mobitex stuff ----------------
  500.  
  501.      Now for the really fun part - your scanner will need to be modified
  502. to allow you to tap off directly from the discriminator output. If you
  503. wait until the signal has gone through the radio's internal audio
  504. filtering the waveform will likely be way too heavily distorted to be
  505. decoded. This is exactly the same problem that our friends who like to
  506. decode pager transmissions run into - some of them have claimed they can
  507. only decode 512 baud pager messages using the earphone output of their
  508. scanner. These transmissions are 8000 baud so you absolutely must use
  509. the discriminator output. If you don't know where to begin modifying
  510. your scanner you might want to ask those who monitor pagers how to get
  511. the discriminator output for your particular radio.
  512.  
  513.       Those of you who have already built an interface for decoding
  514. pager messages should be able to use that interface with some possibly
  515. minor modifications. For those people starting from scratch - you might
  516. want to check out packages intended for pager decoding such as PD203 and
  517. the interfaces they describe. The following excerpt gives an example of
  518. a decoder that is a good place to start experimenting (lifted out of the
  519. PD203 POCSAG pager decoder shareware documentation):
  520.  
  521. >
  522. >   0.1 uF                    |\ +12v
  523. > ---||-----------------------|- \|
  524. > AF IN    |                  |741 \
  525. > ----     |                  |    /--------------------- Data Out
  526. >     |    \            ------|+ /|  |                    CTS (pin 5/8)
  527. >     |    / 100K       |     |/-12v |                 or DSR (pin 6/6)
  528. >     |    \            |            |
  529. >    GND   /            ----/\/\/\----         GND ------ GND (pin 7/5)
  530. >          |            |    100K
  531. >          |            \                  N.B. Pin Numbers for com port are
  532. >         GND           /                  given as x/y, where x is for a 25
  533. >                       \  10K             way, y for a 9 way.
  534. >                       /
  535. >                       |
  536. >                      GND
  537. >
  538. > The  above circuit is a Schmitt Trigger, having thresholds of about +/- 1v.
  539. > If such a large threshold is not required, eg for a  discriminator  output,
  540. > then  the  level of positive feedback may be reduced by either reducing the
  541. > value of the 10K resistor or by increasing the value of the  100K  feedback
  542. > resistor.
  543. >
  544. > The +/- 12v for the op-amp can be derived from unused signals  on  the  COM
  545. > port (gives more like +/- 10v but works fine !):-
  546. >
  547. >
  548. >    TxD (2/3) --------------|<-------------------------------------- -12v
  549. >                                     |                  |
  550. >    RTS (4/7) --------------|<--------       GND        - -
  551. >                   |                          |         _ +  10uF
  552. >                    --------->|-------        - -       |
  553. >                    Diodes 1N4148    |        - + 10uF  GND
  554. >                                     |        |
  555. >    DTR (20/4) ------------->|-------------------------------------- +12v
  556. >
  557.  
  558. DO NOT use the RI (ring indicator) as an input to the computer.
  559.  
  560. The authors strongly suggest tying the non-inverting (+) input of the
  561. op-amp to ground since you are working directly with the discriminator
  562. output and don't need a Schmitt trigger.
  563.  
  564.      As an example, the authors are currently using the using the above
  565. circuit with the following characteristics:
  566.  
  567.     1. The non-inverting input was tied straight to ground
  568.     2. The capacitance value was reduced to 0.02 microfarads.
  569.     3. The 100K resistor at the capacitor was raised to 2 MegaOhms
  570.     4. The op-amp used was an LF411
  571.  
  572. These changes were done primarily to reduce the loading on the
  573. discriminator output circuitry of the scanners used (one presumes the
  574. intial audio stages have high impedances). The capacitance had been
  575. reduced to 0.02uF to avoid the following problems while monitoring
  576. Motorola Mobile data terminals - when a transmitter kicked on it took
  577. such a long time for the DC level discriminator output to re-establish
  578. itself that the very first message was often cut off. In fact, when
  579. monitoring Motorola MDC4800 mobile data terminals the authors feel it
  580. prudent to revert back to a 100Kohm resistor. The moral of this story is
  581. play around and use your oscillscope to verify the interface is working
  582. exactly right!
  583.  
  584.      Interface checking - use of the PD203 POCSAG pager decoding program
  585. is a good test. Additionally, the included program will tell you whether
  586. it thinks the interface is working during the startup process. This test
  587. only means that the input lines on the serial port are successfully
  588. changing states. It doesn't guarantee that your interface or scanner is
  589. suitable for 8000 baud operation.
  590.  
  591.      Keep in mind that depending on your scanner and interface you may
  592. need to set the /BI:1 option in the program to invert the polarity of
  593. the incoming data.
  594.  
  595.      A few words about your scanner - the receive bandwidth must be wide
  596. enough to pass the 12.5KHz wide Mobitex channel without problems. I
  597. doubt this will a problem for any scanner since they are built to
  598. receive 25KHz channels. However, if you have a narrow FM mode setting
  599. for 12.5 KHz channels then the filtering might produce too much
  600. distortion. So you might want to start experimenting with the regular
  601. setting that you use to monitor 25 KHz channels.
  602.  
  603. ***********************************************************************
  604. 7.                A Few words about the program
  605. ***********************************************************************
  606.  
  607.      Remember - don't run this under Windows. DO NOT use control-c
  608. unless you enjoy rebooting your computer on a regular basis (but you're
  609. probably used to doing that with Microsoft products). To exit this
  610. program hit any key on the keyboard. This program does not accept any
  611. sort of keyboard input - all configurations are done with the command
  612. line arguements listed below. An example of this would be (assuming you
  613. called your program executable is called "mobitex.exe"):
  614.  
  615. mobitex /v:1 /cfs:0 /rn:0 /com:2
  616.  
  617. By default the program stores all received data in a file starting with
  618. MOBYDA. Each time the program is run it picks a new filename so that
  619. your previously captured data will not be overwritten. The program
  620. defaults are set for operation with RAM's mobitex network (the only
  621. parameter you might need to set is the bit inversion option which will
  622. depend on your particular scanner and interface). The authors suggest
  623. using a one line batch file with all the configuration information in it
  624. for each type of system you will want to monitor.
  625.  
  626.      By default, the program assumes you will be listening to a base
  627. station, not a portable computer.
  628.  
  629.      Finally, are you worried that your computer is too slow to keep up
  630. with this mess? The very last number that the program prints to the
  631. screen gives approximately the maximum value of how full the receive
  632. buffer got. On the authors' systems running fast Pentiums this value
  633. rarely exceeds 100 out of the full 15000 word buffer length.
  634.  
  635. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  636. Summary and explanation of program command line arguement options
  637.  
  638. VERBOSE MODE: when enabled the program will show all received frame sync
  639.   and control bytes as they are received. You will want to set this
  640.   mode if you are examing an unknown system and want to verify that
  641.   this is indeed a Mobitex system.
  642.   /V:1        - print received system frame sync and control bytes
  643.   /V:0        - don't show the above (DEFAULT)
  644.  
  645. CHECK FRAME SYNC: If the frame sync option is correctly set for the
  646.   system you are monitoring then enable this option to better allow the
  647.   program to decode incoming data. If you don't know the frame sync
  648.   disable this option and enable the /V option to find out what it is.
  649.   /CFS:1      - check system specific frame sync field (DEFAULT).
  650.   /CFS:0      - Don't check it - useful for unknown systems.
  651.  
  652. FRAME SYNC: Each system is allowed to have its own frame sync sequence.
  653.   This option allows you to set it to whatever your particular system is
  654.   using. Once the proper Frame sync is specified you can enable the CFS
  655.   option.
  656.   /FS:XXXX    - set system specific frame sync to HEX XXXX (DEFAULT B433)
  657.  
  658. BIT SYNC: The Mobitex standard specifies that this should be CCCC for
  659.   transmissions from a base station. The only reason that this is a user
  660.   option is because if you want to listen to the mobile transmissions
  661.   you must change this setting to 3333. These are the only two settings
  662.   that you should ever need.
  663.   /SY:YYYY    - set bit sync to HEX YYYY (Default for base stations CCCC)
  664.  
  665. BAUD RATE: You can tell the program to run at virtually any baud rate
  666.   you want. If you don't know the baud rate of an unknown system you
  667.   probably should look at your received waveform on an oscilloscope.
  668.   /BR:Z       - Z is the Mobitex system's baud rate (Default = 8000).
  669.  
  670. BIT SCRAMBLING: This option allows you to turn the bit scrambling off if
  671.   needed although the authors guess that most systems will be using it.
  672.   /BS:1       - System uses bit scrambling (DEFAULT)
  673.   /BS:0       - system does not use bit scrambling
  674.  
  675. RECEIVE CLOCK ADJUSTEMENTS: The crystal controlling your computer's
  676.   serial port might be slightly different from the author's. The current
  677.   routine will attempt to make up for this variation (within +/- 5 ns)
  678.   of the 840ns clock.
  679.   /CA:1       - program attempts to fine tune receive clock (DEFAULT)
  680.   /CA:0       - program does not attemp to fine tune receive clock.
  681.  
  682. BIT INVERSION: Your scanner and interface combination may invert the
  683.   incoming data. If so this option must be set.
  684.   /BI:1       - Inverts incoming raw data.
  685.   /BI:0       - don't invert incoming raw data (DEFAULT).
  686.  
  687. RAM NETWORK mode: If set, the program decides that a sync and control byte
  688.   sequence is followed by data blocks if the second control byte has
  689.   bits 1 and 2 zero. If not set then the program checks to see if a data
  690.   block follows EVERY sync/control byte sequence. This probably should
  691.   be set to zero for non-RAM systems.
  692.   /RN:1       - RAM only: control bytes determine if data blocks follow sync.
  693.   /RN:0       - always try to decode data blocks regardless of control bytes.
  694.  
  695. OUTPUT FILE: If you don't want data written to an output file (with a
  696.   unique filename) disable this option. This might be useful for
  697.   troubleshooting if you suspect disk access is causing problems.
  698.   /OF:1       - Write data to output file (DEFAULT).
  699.   /OF:0       - Don't write output data file.
  700.  
  701. COM PORT: Allows you to set which com port you want to use with your
  702.   interface.
  703.   /COM:z      - set z = 1,2,3,4 to set com port you want to use.
  704.  
  705.  
  706. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  707. Suggested procedure for an unknown Mobitex system:
  708.  
  709. 1. Find out the correct baud rate. Best bet - use an oscilloscope.
  710.  
  711. 2. Start out with following options set: /RN:0 /CFS:0 /v:1
  712.  
  713. 3. If you don't known whether you need to invert the incoming data the
  714. authors suggest the following procedure: try both /BI:0 and /BI:1
  715. options. The correct setting will probably be the one which gets good
  716. control bytes (you don't see the "BAD Control Byte FEC" message as
  717. often).
  718.  
  719. 4. You want to look at those lines with good control bytes and indentify
  720. the system specific Frame sync. From now on, when you want to monitor
  721. this system use the /FS: and /CFS:1 options to tell the program to
  722. actively check for this frame sync. If things are working reasonably
  723. well at this point you should only good control bytes appearing on the
  724. screen every time you hear some data coming over the channel.
  725.  
  726. 5. At this point the only option you have left to play with is the /BS:
  727. option. You will known if the /BS: option is correctly set when you see
  728. valid data blocks appearing on the screen - they will look something
  729. like :
  730.  
  731. 6F6C6F6775653A2049424D204D6F62696C65A73B         ologue: IBM Mobileß;
  732.  
  733. If you see any blocks of this form then all parameters are correctly set
  734. - such blocks had to go through several hurdles involving forward error
  735. correction and a CRC check and would have not been displayed if program
  736. parameters have been incorrectly set.
  737.  
  738. 6. Sit back and snarf the data. In order not to see the same frame sync
  739. and control bytes from appearing over and over you now probably will
  740. want to set the /V:0 option. Keep in mind that very little actual data
  741. may be flowing over the network you are monitoring. Because of this the
  742. authors have been known to leave their computers and scanners monitoring
  743. a specific Mobitex system all day while they are off at work.
  744.  
  745. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  746.  
  747.      As far as compiling this - save the latter portion of this posting
  748. (the program listing) and feed it to a C compiler. Pretty much any C
  749. compiler from Borland should work. If you (Heaven Forbid) use a
  750. Microsoft C compiler you might need to rename some calls such as
  751. outport. Follow any special instructions for programs using their own
  752. interrupt service routines (my compiler package recommends turning the
  753. "Use register variables", and "stack warning" compile options off). It
  754. also does not want anything whatsoever to do with Windows. Please don't
  755. even think about running this program under Windows.
  756.  
  757. ***********************************************************************
  758. 8.               Finally - the program listing itself
  759. ***********************************************************************
  760.  
  761. ---------------------- C u t   H e r e ! ! ! --------------------------
  762.  
  763. #include <stdio.h>
  764. #include <conio.h>
  765. #include <dos.h>
  766. #include <math.h>
  767. #include <string.h>
  768.  
  769. /************************************************************************/
  770. /*                  GLOBAL VARIABLE DECLARATIONS                        */
  771. /************************************************************************/
  772. int lc=0;
  773. char ob[1000];  /* output buffer for packet before being sent to screen */
  774. int obp=0;    /* pointer to current position in array ob        */
  775. double dtt, odtt,ul,ll; /* variables used in clock tracking routine     */
  776.  
  777. FILE *out;    /* pointer to output file                 */
  778.  
  779. /* configuration parameter declaration to the defaults for RAM network  */
  780. static int verbose = 0; /* verbose mode parameter */
  781. static int cfs = 1;    /* system specific frame sync checking status      */
  782. static int frsync=0xB433;     /* system specific frame sync         */
  783. static int btsync=0xCCCC;    /* bit sync                             */
  784. static double brate = 8000.0;     /* Mobitex system baud rate         */
  785. static int bitscr = 1;           /* bit scrambling in use ?         */
  786. static int clocka = 1;           /* fine tune receive clock          */
  787. static int bitinv = 0;          /* bit inversion             */
  788. static int ramnet = 1;        /* ramnet flag - 1 means it's ram     */
  789. static int outfil = 1;          /* file output toggle                   */
  790. static int comport = 0x3f8;    /* serial port base address; set in main*/
  791. static int tempo=0;          /* maybe I should get a new compiler    */
  792.  
  793. /* data buffer for raw data coming in over serial port            */
  794. static unsigned int buflen= 15000;      /* length of data buffer          */
  795. static volatile unsigned int cpstn = 0; /* current position in buffer     */
  796. static unsigned int fdata[15001] ;      /* frequency data array           */
  797.  
  798. void interrupt (*oldfuncc) (); /* vector to old com port interrupt        */
  799.  
  800.  
  801. /************************************************************************/
  802. /*                 SERIAL PORT INTERRUPT HANDLER                        */
  803. /************************************************************************/
  804. /*                                this is serial com port interrupt       */
  805. /* we assume here that it only gets called when one of the status       */
  806. /* lines on the serial port changes (that's all you have hooked up).    */
  807. /* All this handler does is read the system timer (which increments     */
  808. /* every 840 nanoseconds) and stores it in the fdata array. The MSB     */
  809. /* is set to indicate whether the status line is zero. In this way      */
  810. /* the fdata array is continuously updated with the length and the      */
  811. /* length and polarity of each data pulse for further processing by     */
  812. /* the main program.                                */
  813. void interrupt com1int()
  814. {
  815.   static unsigned int d1,d2,ltick,tick,dtick;
  816.  
  817.   /* the system timer is a 16 bit counter whose value counts down     */
  818.   /* from 65535 to zero and repeats ad nauseum. For those who really  */
  819.   /* care, every time the count reaches zero the system timer           */
  820.   /* interrupt is called (remember that thing that gets called every  */
  821.   /* 55 milliseconds and does housekeeping such as checking the       */
  822.   /* keyboard).                                                       */
  823.   outportb (0x43, 0x00);       /* latch counter until we read it      */
  824.   d1 = inportb (0x40);         /* get low count                       */
  825.   d2 = inportb (0x40);         /* get high count                      */
  826.  
  827.   /* get difference between current, last counter reading             */
  828.   tick  = (d2 << 8) + d1;
  829.   dtick = ltick - tick;
  830.   ltick = tick;
  831.  
  832.   /* set MSB to reflect state of input line */
  833.   if ((inportb(comport + 6) & 0xF0) > 0) dtick = dtick | 0x8000;
  834.                   else dtick = dtick & 0x3fff;
  835.  
  836.   fdata[cpstn] = dtick;        /* put freq in fdata array             */
  837.   cpstn  ++;                   /* increment data buffer pointer       */
  838.   if (cpstn>buflen) cpstn=0;   /* make sure cpstn doesnt leave array  */
  839.  
  840.   d1 = inportb (comport + 2);   /* clear IIR                           */
  841.   d1 = inportb (comport + 5);   /* clear LSR                           */
  842.   d1 = inportb (comport + 6);   /* clear MSR                           */
  843.   d1 = inportb (comport);       /* clear RX                            */
  844.   outportb (0x20, 0x20);       /* this is the END OF INTERRUPT SIGNAL */
  845.                                /* "... that's all folks!!!!"          */
  846. }
  847.  
  848. /************************************************************************/
  849. /*                  SERIAL PORT INITIALIZATION                          */
  850. /************************************************************************/
  851. /* basic purpose: enable modem status interrupt and set serial port     */
  852. /*          output lines to supply power to interface             */
  853. void set8250 ()                /* sets up the 8250 UART               */
  854. {
  855.   static unsigned int t;
  856.   outportb (comport+3, 0x00);  /*  set IER on 0x03f9                  */
  857.   outportb (comport+1, 0x08);  /*  enable MODEM STATUS INTERRUPT      */
  858.   outportb (comport+4, 0x0a);  /*  push up RTS, DOWN DTR              */
  859.   t = inportb(comport + 5);    /*  clear LSR                          */
  860.   t = inportb(comport);        /*  clear RX                           */
  861.   t = inportb(comport + 6);    /*  clear MSR                          */
  862.   t = inportb(comport + 2);    /*  clear IID                          */
  863.   t = inportb(comport + 2);    /*  clear IID - again to make sure     */
  864. }
  865.  
  866. /************************************************************************/
  867. /*                    TIMER CHIP INITIALIZATION                         */
  868. /************************************************************************/
  869. /* purpose: make sure computer timekeeper is set up properly. This      */
  870. /*          routine probably isn't necessary - it's just an insurance   */
  871. /*        policy.                                                     */
  872. void set8253()                 /*  set up the 8253 timer chip         */
  873. {                              /* NOTE: ctr zero, the one we are using*/
  874.                                /*  is incremented every 840nSec, is   */
  875.                                /*  main system time keeper for dos    */
  876.   outportb (0x43, 0x34);       /* set ctr 0 to mode 2, binary         */
  877.   outportb (0x40, 0x00);       /* this gives us the max count         */
  878.   outportb (0x40, 0x00);
  879. }
  880.  
  881. /************************************************************************/
  882. /*          minor forward error correcting stuff stuff...               */
  883. /************************************************************************/
  884. /* do error correcting stuff */
  885.  
  886. /* matrix for block encoding */
  887. int h3 = 0xEC, h2 = 0xD3, h1 = 0xBA, h0 = 0x75;
  888.  
  889. /* returns the number of ones in the byte passed to routine */
  890. int ones(int h)
  891. {
  892.   static int i,nb;
  893.   nb = 0;
  894.   for (i=0; i<8; i++)
  895.   {
  896.     if ((h & 0x01) == 1) nb++;
  897.     h = h >> 1;
  898.   }
  899.   return(nb);
  900. }
  901.  
  902. /* returns number of ones in the integer passed to routine */
  903. int ones_int(int h)
  904. {
  905.   return(ones(h) + ones(h >> 8));
  906. }
  907.  
  908. /************************************************************************/
  909. /*          RUN THROUGH BLOCK FORWARD ERROR CORRECTION CODE             */
  910. /************************************************************************/
  911. /* PURPOSE:                                                           */
  912. /*       does FEC on the 8 data bits and 4 FEC bits passed to it in goi */
  913. /*       blert tries to check and correct errors... If the errors are   */
  914. /*       uncorrectable blert returns a 1 ; otherwise 0                  */
  915. /*       but don't read too much into this - two thirds of the time     */
  916. /*       random crap going into this routine will not generate the      */
  917. /*       uncorrectable error signal... Please Rely on the CRC check     */
  918. int blert(int *goi)
  919. {
  920.    static int dab,nb,bb,uce=0;
  921.  
  922.    uce = 0;  /* flag that indicates an uncorrectable error */
  923.  
  924.    /* calculate ecc bits from our current info bits */
  925.    dab = *goi >> 4;
  926.    nb  = (ones(dab & h3) & 0x01) << 3;
  927.    nb += (ones(dab & h2) & 0x01) << 2;
  928.    nb += (ones(dab & h1) & 0x01) << 1;
  929.    nb += (ones(dab & h0) & 0x01);
  930.  
  931.    /* get syndrome */
  932.    nb = nb ^ (*goi & 0x0f);
  933.  
  934.    if (ones(nb) > 0) uce = 1; else uce = 0;
  935.    /* if syndrome is not equal to zero try to correct the bad bit */
  936.    if (ones(nb) > 1)
  937.    {
  938.      if ((nb & 0x08) > 0) bb  = h3; else bb  = h3 ^ 0xff;
  939.      if ((nb & 0x04) > 0) bb &= h2; else bb &= h2 ^ 0xff;
  940.      if ((nb & 0x02) > 0) bb &= h1; else bb &= h1 ^ 0xff;
  941.      if ((nb & 0x01) > 0) bb &= h0; else bb &= h0 ^ 0xff;
  942.  
  943.      /* are we pointing to a single bit? if so we nailed the bastard */
  944.      if ( ones(bb) == 1) *goi = *goi ^ (bb<<4); else uce ++;
  945.    }
  946.    else *goi = *goi ^ nb;
  947.    /* single wrong bit in syndrome => error occured in FEC bits */
  948.  
  949.    return(uce);
  950. }
  951.  
  952. /************************************************************************/
  953. /*               BIT SCRAMBLING SEQUENCE GENERATOR                      */
  954. /************************************************************************/
  955. /* following is the pseudo-random bit scrambling generator.              */
  956. /* It's the output of a 9 stage linear-feedback shift register with taps */
  957. /* at position 5 and 9 XORed and fed back into the first stage.          */
  958. /* An input of less than zero resets the scrambler.                      */
  959. /* Otherwise it returns one bit at a time each time it is called         */
  960. int bs(int st)
  961. {
  962.   static int rs,ud;
  963.  
  964.   /* leave if system isn't supposed to use bit scrambling */
  965.   if (bitscr == 0) return(0);
  966.  
  967.   if (st < 0) rs = 0x1E;  /* inputs <0 reset scrambler */
  968.   else
  969.   {
  970.     if ( (rs & 0x01) > 0) ud=1; else ud = 0;
  971.     if ( (rs & 0x10) > 0) ud = ud ^ 0x01;
  972.     rs = rs >> 1;
  973.     if (ud > 0) rs = rs ^ 0x100;
  974.   }
  975.   return(ud);
  976. }
  977.  
  978. /************************************************************************/
  979. /*                       CRC GENERATING ROUTINE                         */
  980. /************************************************************************/
  981. /* CRC generator - passing a -1 to this routine resets it, otherwise */
  982. /* pass all 144 data bits in the mobitex data block to it (starting  */
  983. /* with byte 0, LSB bit). The returned value will then be the        */
  984. /* CRC value. Passing any other negative value just returns CRC.     */
  985. unsigned int crc(signed int gin)
  986. {
  987.   static unsigned int sr = 0x00,cr;
  988.  
  989.   if (gin >= 0)
  990.   {
  991.     if (gin == 1) cr = cr ^ sr;
  992.     if ((sr & 0x8000) != 0) sr = (sr << 1) ^ 0x0811; else sr = sr << 1;
  993.   }
  994.   else if (gin == -1)                     /* -1 resets the crc state */
  995.   {
  996.     sr = 0xF8E7;
  997.     cr = 0x2A5D;
  998.   }
  999.  
  1000.   return(cr);
  1001. }
  1002.  
  1003.  
  1004. /**********************************************************************/
  1005. /*          PROCESS RECEIVED 240 BIT MOBITEX DATA BLOCK               */
  1006. /**********************************************************************/
  1007. /* process MOBITEX data block */
  1008. int barfrog()
  1009. {
  1010.   static int i,j,k,b,nerr,cb;
  1011.   static unsigned int crcc=0x0000;
  1012.   static int blob[30];
  1013.   nerr = 0;
  1014.  
  1015.   /* process data block into 20 byte chunk stored in array blob */
  1016.   crc(-1);            /* reset crc routine */
  1017.   crcc = 0x0000;
  1018.   for (i=0; i<20; i++)
  1019.   {
  1020.     /* uninterleave the data into b (holds 8 data bits + 4 FEC bits) */
  1021.     b = 0;
  1022.     for (j = 0; j<12; j++)
  1023.     {
  1024.       b = b << 1;
  1025.       k = (j*20) + i;
  1026.       if (ob[k] == 49) b ^= 0x01;
  1027.     }
  1028.  
  1029.     /* run through error correction routine */
  1030.     nerr+=blert(&b);
  1031.  
  1032.     /* spit out data bits to CRC routine - LSB data bit first... */
  1033.     cb = b >> 4;
  1034.     if (i < 18)
  1035.     {
  1036.       for (j=0; j<8; j++)
  1037.       {
  1038.     if ( (cb & 0x01) == 1) crc(1); else crc(0);
  1039.     cb = cb >> 1;
  1040.       }
  1041.     }
  1042.     else
  1043.     {
  1044.       crcc = (crcc << 8) ^ (cb & 0xff) ;
  1045.     }
  1046.  
  1047.     /* store the byte in our wonderful wonderful array */
  1048.     b = b >> 4;
  1049.     blob[i] = b;
  1050.   }
  1051.  
  1052.   /* at this point array BLOB holds the data; nerr gives the number  */
  1053.   /* of errors detected by the FEC code ('corrected' errors count as */
  1054.   /* one, uncorrectable count as 2); and crcc gives the received     */
  1055.   /* CRC code. We use this info to decide if we got a good block     */
  1056.  
  1057.   /* if CRC is correct or nerr <15 we'll say it's a good block */
  1058.   if ( (crc(-2) == crcc) | (nerr < 15) )
  1059.   {
  1060.     for (i=0; i<20; i++)
  1061.     {
  1062.       printf("%02X",blob[i]);
  1063.       if (outfil) fprintf(out,"%02X",blob[i]);
  1064.     }
  1065.     if ( crc(-2) == crcc)
  1066.     {
  1067.       printf ("         ");
  1068.       if (outfil) fprintf (out,"         ");
  1069.     }
  1070.     else
  1071.     {
  1072.       printf(" BAD CRC ");
  1073.       if (outfil) fprintf(out," BAD CRC ");
  1074.     }
  1075.     for (i=0; i<20; i++) if (blob[i] > 31)
  1076.     {
  1077.       printf ("%c",blob[i]);
  1078.       if (outfil) fprintf (out,"%c",blob[i]);
  1079.     }
  1080.     else
  1081.     {
  1082.       printf (".");
  1083.       if (outfil) fprintf(out,".");
  1084.     }
  1085.     printf("\n");
  1086.     if (outfil) fprintf(out,"\n");
  1087.   }
  1088.  
  1089.   return(nerr);
  1090. }
  1091.  
  1092. /************************************************************************/
  1093. /*              FRAME SYNCHRONIZATION OF RAW BIT STREAM                 */
  1094. /************************************************************************/
  1095. /* this routine tries to achieve frame sync up in the raw bit stream      */
  1096. int frame_sync(char gin)
  1097. {
  1098.   static int s1=0x0000,s2=0x0000;
  1099.   static int cb1,cb2,bc=0,nbc=0,og,nu,bcb,fss = 0,fsb;
  1100.  
  1101.   fss = 0;
  1102.   /* nbc is a bit counter for # of bits left to form into a data block */
  1103.   if (nbc == 0)
  1104.   {
  1105.     /* nbc = 0 so we aren't trying to process a data block; instead try */
  1106.     /* to sync up with incoming bit stream                              */
  1107.  
  1108.     /* keep sliding buffers up to date */
  1109.     s1 = s1 << 1;
  1110.     if ( (s2 & 0x8000) != 0) s1++;
  1111.     s2 = s2 << 1;
  1112.     if (gin == 49) s2++;
  1113.  
  1114.     /* check for sync */
  1115.     fsb = ones_int(s1^btsync);
  1116.     if (cfs) fsb += ones_int(s2^frsync);
  1117.     /* if first two integers match up within a bit or two then     */
  1118.     /* we've gotten frame sync                    */
  1119.     if ( (fsb < (1+cfs)) && (bc == 0) )
  1120.     {
  1121.       if (verbose)
  1122.       {
  1123.     printf("SYSTEM FRAME SYNC %04X  ;",s2);
  1124.     if (outfil) fprintf(out,"SYSTEM FRAME SYNC %04X  ;",s2);
  1125.       }
  1126.       bc = 25;
  1127.     }
  1128.  
  1129.     /* bc is a bit counter used to pick off the two status bytes and  */
  1130.     /* the FEC byte in the header.                                    */
  1131.     if (bc > 0)
  1132.     {
  1133.       bc--;
  1134.       if (bc == 0)
  1135.       {
  1136.     /* strip off control bytes, run them through FEC routine */
  1137.     cb1 = (s1 & 0xff) << 4;
  1138.     cb1 += (s2 >> 4) & 0xf;
  1139.     cb2 = (s2 >> 4) & 0xff0;
  1140.     cb2 += (s2 & 0xf);
  1141.     bcb = blert(&cb1) + blert(&cb2);
  1142.     if (bcb == 0) fss = 1;
  1143.     if (verbose)
  1144.     {
  1145.       printf ("Control Bytes #1=%02X, #2=%02X",cb1>>4,cb2>>4);
  1146.       if (outfil) fprintf (out,"Control Bytes #1=%02X, #2=%02X",
  1147.                            cb1>>4,cb2>>4);
  1148.       if (bcb != 0)
  1149.       {
  1150.         printf (" BAD Control Byte FEC");
  1151.         if (outfil) fprintf (out," BAD Control Byte FEC");
  1152.       }
  1153.       printf("\n");
  1154.       if (outfil) fprintf(out,"\n");
  1155.     }
  1156.  
  1157.     /* for RAM network -                                            */
  1158.     /*  control byte2 : bits 1 and 2 both 0 -> data block(s) follow */
  1159.     /* otherwise just be adventurous and see if we get a valid block */
  1160.     if (ramnet) { if ( (cb2 & 0x60) == 0) nbc = 1440; }
  1161.             else nbc = 1440;
  1162.     nu = 0;
  1163.     bs(-1);
  1164.       }
  1165.     }
  1166.   }
  1167.   else
  1168.   {
  1169.     if (bs(1) == 1) og = gin ^ 0x01; else og = gin;
  1170.     ob[nu] = og;
  1171.     nu ++;
  1172.     if (nu == 240)
  1173.     {
  1174.       nu = 0 ;
  1175.       if (barfrog() < 15) nbc = 241; else nbc = 1;
  1176.     }
  1177.     nbc --;
  1178.     if (nbc == 0)
  1179.     {
  1180.       printf ("\n");
  1181.       if (outfil) fprintf(out,"\n");
  1182.     }
  1183.   }
  1184.   return (fss);
  1185. }
  1186.  
  1187. /************************************************************************/
  1188. /*                    RECEIVE CLOCK TWEAKING ROUTINE                    */
  1189. /************************************************************************/
  1190. void check_clk(int i, int nbs)
  1191. {
  1192.   static int nt,ii,ndt,na=0;
  1193.   static double a=0.0,avg,cvg;
  1194.  
  1195.   if (clocka)
  1196.   {
  1197.  
  1198.     ii = i-1;
  1199.     if (ii < 0) ii = buflen;
  1200.     nt = 0;
  1201.     ndt = 0;
  1202.     while (ndt < (54-nbs) )
  1203.     {
  1204.       nt += fdata[ii];
  1205.       ndt = 0.5 + (nt/odtt);
  1206.       ii--;
  1207.       if (ii < 0) ii = buflen;
  1208.     }
  1209.     cvg = (double) nt / ndt;
  1210.  
  1211.     /* update average if in roughly the right range */
  1212.     if ( (cvg < ul) && (cvg > ll))
  1213.     {
  1214.       a = a + cvg;
  1215.       na ++;
  1216.       avg = a / (double) na;
  1217.       dtt = avg;
  1218.     }
  1219.   }
  1220. }
  1221.  
  1222. /************************************************************************/
  1223. /*                         DISPLAY HELP SCREEN                          */
  1224. /************************************************************************/
  1225. void help()
  1226. {
  1227.   printf("\n  MOBITEX RECEIVING PROGRAM - Command line arguement summary\n");
  1228.   printf("      (Defaults are set up for RAM Mobile Data's system.)\n\n");
  1229.   printf("  /V:1        - print received system frame sync and control blocks\n");
  1230.   printf("  /V:0        - don't show the above (DEFAULT)\n");
  1231.   printf("  /CFS:1      - check system specific frame sync field (DEFAULT).\n");
  1232.   printf("  /CFS:0      - Don't check it - useful for unknown systems.\n");
  1233.   printf("  /FS:XXXX    - set system specific frame sync to HEX XXXX (DEFAULT B433)\n");
  1234.   printf("  /SY:YYYY    - set bit sync to HEX YYYY (Default for base stations CCCC)\n");
  1235.   printf("  /BR:Z       - Z is the Mobitex system's baud rate (Default = 8000).\n");
  1236.   printf("  /BS:1       - System uses bit scrambling (DEFAULT)\n");
  1237.   printf("  /BS:0       - system does not use bit scrambling\n");
  1238.   printf("  /CA:1       - program attempts to fine tune receive clock (DEFAULT)\n");
  1239.   printf("  /CA:0       - program does not attemp to fine tune receive clock.\n");
  1240.   printf("  /BI:1       - Inverts incoming raw data.\n");
  1241.   printf("  /BI:0       - don't invert incoming raw data (DEFAULT).\n");
  1242.   printf("  /RN:1       - RAM only: control bytes determine if data blocks follow sync.\n");
  1243.   printf("  /RN:0       - always try to decode data blocks regardless of control bytes.\n");
  1244.   printf("  /OF:1       - Write data to output file (DEFAULT).\n");
  1245.   printf("  /OF:0       - Don't write output data file.\n");
  1246.   printf("  /COM:z      - set z = 1,2,3,4 to set com port you want to use.\n");
  1247.   printf("\nSee text file for further details...");
  1248.   printf(" press any key to continue...\n");
  1249.   getch();
  1250. }
  1251.  
  1252. /************************************************************************/
  1253. /*                            MAIN ROUTINE                              */
  1254. /************************************************************************/
  1255. void main (int argc,char *argv[],char *env[])
  1256. {
  1257.   unsigned int n,i=0,j=0,k,l,nbs,imax=0;
  1258.   int sport=1,irqv=0x0c;
  1259.   char s=48,temp[20],yon[2][5]= {"OFF","ON"};
  1260.   double pl,dt,exc=0.0,clk=0.0,xct;
  1261.  
  1262.   /* process command line arguements */
  1263.   for (n=1; n<argc; n++)
  1264.   {
  1265.     strcpy(temp,argv[n]);
  1266.     strupr(temp);
  1267.     j+=sscanf(temp,"/FS:%X",&frsync);
  1268.     j+=sscanf(temp,"/SY:%X",&btsync);
  1269.     j+=sscanf(temp,"/V:%i",&verbose);
  1270.     j+=sscanf(temp,"/CFS:%i",&cfs);
  1271.     j+=sscanf(temp,"/BR:%g",&brate);
  1272.     j+=sscanf(temp,"/BS:%i",&bitscr);
  1273.     j+=sscanf(temp,"/CA:%i",&clocka);
  1274.     j+=sscanf(temp,"/BI:%i",&bitinv);
  1275.     j+=sscanf(temp,"/RN:%i",&ramnet);
  1276.     j+=sscanf(temp,"/OF:%i",&outfil);
  1277.     j+=sscanf(temp,"/COM:%i",&sport);
  1278.     if (temp[1] == 'H') j=30;
  1279.   }
  1280.  
  1281.   if ( (j+1) != argc) help();
  1282.   printf ("\n\nProgram Options set as follows: \n");
  1283.           printf ("Baud Rate        : %g baud\n",brate);
  1284.           printf ("Frame sync       : %04X\n",frsync);
  1285.           printf ("Bit sync         : %04X\n",btsync);
  1286.   cfs    &= 0x01; printf ("Check frame sync : %s\n",yon[cfs]);
  1287.   verbose&= 0x01; printf ("Verbose mode     : %s\n",yon[verbose]);
  1288.   bitscr &= 0x01; printf ("Bit scrambling   : %s\n",yon[bitscr]);
  1289.   clocka &= 0x01; printf ("Fine tune clock  : %s\n",yon[clocka]);
  1290.   bitinv &= 0x01; printf ("Bit Inversion    : %s\n",yon[bitinv]);
  1291.   ramnet &= 0x01; printf ("RAM network mode : %s\n",yon[ramnet]);
  1292.   outfil &= 0x01; printf ("Output file echo : %s\n",yon[outfil]);
  1293.   sport  &= 0x03; printf ("Running  on  COM%i\n\n",sport);
  1294.  
  1295.   if (outfil)
  1296.   {
  1297.     strcpy (temp,"MOBYDAXXXXXX");
  1298.     mktemp(temp);
  1299.     printf("\nfilename where screen display will be echoed : %s\n\n",temp);
  1300.     out = fopen(temp,"wt");
  1301.   }
  1302.  
  1303.   printf ("Press any key to stop program...\n\n");
  1304.  
  1305.   /* dtt is the number of expected clock ticks per bit                 */
  1306.   dtt =  1.0/(brate*839.22e-9);      /* this will be the updated clock */
  1307.   odtt = dtt;                              /* this oddt is not updated */
  1308.   /* following give the range over which the the clock can be adjusted */
  1309.   ul = odtt + 1.0;
  1310.   ll = odtt - 1.0;
  1311.  
  1312.   /* set up serial port and related parameters                          */
  1313.   n = inportb (0x21);
  1314.   if ( (sport == 1) | (sport == 3))
  1315.   {
  1316.     irqv = 0x0c;
  1317.     oldfuncc = getvect(irqv);    /* save COM  Vector                    */
  1318.     setvect (irqv, com1int);     /* Capture COM  vector                 */
  1319.     outportb(0x21, n & 0xef);
  1320.     if (sport == 1) comport = 0x3f8; else comport = 0x3e8;
  1321.   }
  1322.   else
  1323.   {
  1324.     irqv = 0x0b;
  1325.     oldfuncc = getvect(irqv);    /* save COM  Vector                    */
  1326.     setvect (irqv, com1int);     /* Capture COM  vector                 */
  1327.     outportb(0x21, n & 0xf7);
  1328.     if (sport == 2) comport = 0x2f8; else comport = 0x2e8;
  1329.   }
  1330.  
  1331.   set8253();                   /* set up 8253 timer chip              */
  1332.  
  1333.   set8250();                   /* set up 8250 UART                    */
  1334.  
  1335.   while ( (cpstn < 3) & (kbhit() == 0) );
  1336.   if (cpstn < 3)
  1337.   printf("HEY - no data seems to be coming in over your interface.\n\n");
  1338.   else
  1339.   printf("Interface seems to work properly...\n\n");
  1340.  
  1341.   /* main process routine - keeps on going until any key was hit      */
  1342.   while (kbhit() == 0)
  1343.   {
  1344.    if (i != cpstn)
  1345.    {
  1346.     if  ( ( fdata[i] & 0x8000) != 0) s = 48; else s = 49;
  1347.     s = s ^ bitinv;
  1348.  
  1349.     /* add in new number of cycles to clock  */
  1350.     clk += (fdata[i] & 0x7fff);
  1351.     xct = exc + 0.5 * dtt;  /* exc is current boundary */
  1352.     nbs = 0;
  1353.     while ( clk >= xct )
  1354.     {
  1355.       /* if frame_sync returns a 1 it means the last 56 bits were the sync */
  1356.       /* frame_sync(s); */
  1357.       nbs ++;
  1358.       if (frame_sync(s) == 1) check_clk(i,nbs);
  1359.       clk = clk - dtt;
  1360.     }
  1361.     /* clk now holds new boundary position. update exc slowly... */
  1362.     /* 0.005 sucks; 0.02 better; 0.06 mayber even better; 0.05 seems pretty good */
  1363.     exc = exc + 0.050*(clk - exc);
  1364.  
  1365.     i++;
  1366.     if( i >buflen) i = 0;
  1367.  
  1368.     if ( ((cpstn - i) > imax) && (cpstn > i)) imax = cpstn - i;
  1369.    }
  1370.  
  1371.   }
  1372.  
  1373.   /* shutdown */
  1374.   outportb (0x21, n);          /* disable IRQ4 interrupt              */
  1375.   setvect (irqv, oldfuncc);    /* restore old COM1 Vector             */
  1376.  
  1377.   printf (" %i\n",imax);
  1378.   if (outfil) fclose(out);
  1379. }
  1380.  
  1381. /*                                end of post                         */
  1382.  
  1383.  
  1384.